package com.xbongbong.paas.service.workflow.setting;


import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.constant.WorkflowConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.FieldPermissionEntityExt;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.ConditionListHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.workflow.WorkflowNameAvatarPoJo;
import com.xbongbong.paas.pojo.workflow.WorkflowNodeTreePojo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowGetPojo;
import com.xbongbong.paas.pojo.workflow.settings.vo.FilterConditionVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowOperationsVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.RegexUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormUtil;
import com.xbongbong.paas.util.WorkflowFormulaUtil;
import com.xbongbong.paas.util.WorkflowNodeUtil;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BusinessRuleErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.workflow.WorkflowValueTypeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.product.BusinessProductCompareEnum;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.RoleEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.pojo.FilterCondition;
import com.xbongbong.workflow.pojo.WorkflowOperationsPojo;
import com.xbongbong.workflow.pojo.nodes.WorkflowGetNodeListPojo;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/05/21 14:33
 */
@Component
public abstract class AbstractWorkflowNodeSettings implements WorkflowNodeSettings {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractWorkflowNodeSettings.class);


    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;

    /**
     * 获取表单名称
     * @param workflowGetPojo
     * @param workflowNodeEntity
     * @return java.lang.String
     * @author 吴峰
     * @date 2021/5/24 15:07
     */
    protected List<String> getNodeContent(WorkflowGetPojo workflowGetPojo, WorkflowNodeEntity workflowNodeEntity, String content) {
        List<String> list = new ArrayList<>();
        String formName = getFormName(workflowGetPojo, workflowNodeEntity);
        if (StringUtil.isEmpty(formName)) {
            return new ArrayList<>();
        }
        list.add(String.format(I18nMessageUtil.getMessage(content), formName));
        return list;
    }

    protected String getFormName(WorkflowGetPojo workflowGetPojo, WorkflowNodeEntity workflowNodeEntity) {
        String formName = "";
        Long formId = workflowNodeEntity.getFormId();
        if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), workflowNodeEntity.getBusinessType()) && workflowGetPojo.getWorkOrderFormMap().containsKey(formId)) {
            formName = workflowGetPojo.getWorkOrderFormMap().get(formId).getName();
        } else if (workflowGetPojo.getFormMap().containsKey(formId)) {
            formName = workflowGetPojo.getFormMap().get(formId).getName();
        }
        return formName;
    }

    /**
     * 获取名称和头像
     * @param optionalRangeList
     * @param workflowGetPojo
     * @return com.xbongbong.workflow.pojo.WorkflowNodeTreePojo
     * @author 吴峰
     * @date 2021/5/24 15:07
     */

    protected WorkflowNodeTreePojo getNameAndAvatar(List<? extends OptionalRangeEntity> optionalRangeList, WorkflowGetPojo workflowGetPojo, Integer nodeType) {
        WorkflowNodeTreePojo workflowNodeTreePojo = new WorkflowNodeTreePojo();
        if (CollectionsUtil.isEmpty(optionalRangeList)) {
            return workflowNodeTreePojo;
        }

        WorkflowNameAvatarPoJo workflowNameAvatarPoJo = setOptionRangeList(workflowGetPojo, optionalRangeList);

        List<String> nameList = workflowNameAvatarPoJo.getNameList();
        List<String> avatarList = workflowNameAvatarPoJo.getAvatarList();

        List<String> contentList = new ArrayList<>();
        String memo = WorkflowConstant.APPROVE_NODE;
        if (Objects.equals(WorkflowNodeTypeEnum.SEND_MESSAGE_NODE.getType(), nodeType)) {
            memo = WorkflowConstant.SEND_MESSAGE_NODE;
        } else if (Objects.equals(WorkflowNodeTypeEnum.CC_NODE.getType(), nodeType)) {
            memo = WorkflowConstant.CC_NODE;
        }
        String name = String.format(I18nMessageUtil.getMessage(memo), StringUtils.join(nameList, PaasConstant.COMMA));

        contentList.add(name);

        workflowNodeTreePojo.setContent(contentList);
        workflowNodeTreePojo.setAvatarList(avatarList);
        return workflowNodeTreePojo;
    }

    /**
     * 同步下名称
     * @param workflowGetPojo
     * @param optionalRangeList
     * @return
     */
    protected WorkflowNameAvatarPoJo setOptionRangeList(WorkflowGetPojo workflowGetPojo, List<? extends OptionalRangeEntity> optionalRangeList) {
        if (CollectionsUtil.isEmpty(optionalRangeList)) {
            return new WorkflowNameAvatarPoJo();
        }
        List<String> nameList = new ArrayList<>();
        List<String> avatarList = new ArrayList<>();

        Map<String, UserEntity> userMap = workflowGetPojo.getUserMap();
        Map<Long, DepartmentEntity> departmentMap = workflowGetPojo.getDepartmentMap();
        Map<Integer, RoleEntity> roleMap = workflowGetPojo.getRoleMap();
        optionalRangeList.forEach(item->{
            if (Objects.equals(item.getProperty(), OptionalRangeEnum.USER.getValue())) {
                UserEntity userEntity = userMap.get(item.getId());
                if (Objects.isNull(userEntity)) {
                    return;
                }
                item.setName(userEntity.getName());
                nameList.add(userEntity.getName());
                avatarList.add(userEntity.getAvatar());
            } else if (Objects.equals(item.getProperty(), OptionalRangeEnum.DEPT.getValue())) {
                DepartmentEntity departmentEntity = departmentMap.get(Long.valueOf(item.getId()));
                if (Objects.isNull(departmentEntity)) {
                    return;
                }
                item.setName(departmentEntity.getName());
                nameList.add(departmentEntity.getName());
            }else if (Objects.equals(item.getProperty(), OptionalRangeEnum.ROLE.getValue())) {
                RoleEntity roleEntity = roleMap.get(Integer.valueOf(item.getId()));
                if (Objects.isNull(roleEntity)) {
                    return;
                }
                item.setName(roleEntity.getRoleName());
                nameList.add(roleEntity.getRoleName());
            } else if (Objects.equals(item.getProperty(), OptionalRangeEnum.DYNAMIC_MANAGER.getValue())) {
                nameList.add(item.getName());
            }
        });
        return new WorkflowNameAvatarPoJo(nameList, avatarList);
    }

    /**
     * 根据节点类型，获取当前节点的上方所有的节点
     * @param corpid
     * @param workflowId
     * @param workflowNodeId
     * @return java.util.List<com.xbongbong.workflow.pojo.nodes.WorkflowGetNodeListPojo>
     * @author 吴峰
     * @date 2021/6/3 19:11
     * @throws XbbException
     */
    public List<WorkflowGetNodeListPojo>  getBeforeNodeListByNodeType(String corpid, Long workflowId, Long workflowNodeId, List<Integer> nodeTypeList) throws XbbException {
        try {
            WorkflowEntity workflowEntity =  workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            WorkflowNodeEntity workflowNodeEntity =  workflowNodeModel.getByKey(workflowNodeId, corpid);
            if (Objects.isNull(workflowNodeEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
            }
            List<WorkflowNodeEntity> workflowNodeList = workflowNodeModel.getWorkflowNodeList(corpid, workflowId, " priority " + SortOrder.ASC);

            List<WorkflowNodeEntity> upNodeList = WorkflowNodeUtil.getUpNodeList(workflowNodeList, workflowNodeEntity.getPrevId(), nodeTypeList);

            Set<Long> formIdList = new HashSet<>();
            Set<Long> workOrderIdList = new HashSet<>();
            upNodeList.forEach(item->{
                if (!FormUtil.haveWorkflowPermission(item.getBusinessType(), item.getSaasMark(), DistributorMarkEnum.OTHER.getCode())) {
                    return;
                }
                if(Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getBusinessType())) {
                    workOrderIdList.add(item.getFormId());
                } else {
                    formIdList.add(item.getFormId());
                }
            });
            Map<Long, PaasFormEntity> formMap = proFormHelp.getFormMap(formIdList, corpid, DelEnum.NORMAL.getDel());

            Map<Long, WorkOrderFormEntity> workOrderFormMap = proFormHelp.getWorkOrderFormMap(workOrderIdList, corpid, DelEnum.NORMAL.getDel());
            List<WorkflowGetNodeListPojo> nodeList = new ArrayList<>();
            upNodeList.forEach(item->{

                Integer triggerNodeFlag = 0;
                if (Objects.equals(WorkflowNodeTypeEnum.START_NODE.getType(), item.getType())) {
                    triggerNodeFlag = 1;
                }
                if(Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getBusinessType()) && workOrderFormMap.containsKey(item.getFormId())) {
                    WorkOrderFormEntity workOrderEntity = workOrderFormMap.get(item.getFormId());
                    WorkflowGetNodeListPojo workflowGetNodeListPojo = new WorkflowGetNodeListPojo(item.getWorkflowId(), item.getId(), item.getFormId(), item.getAppId(),
                            item.getMenuId(), item.getSaasMark(), item.getBusinessType(), workOrderEntity.getName(), item.getName(), 1, triggerNodeFlag);
                    nodeList.add(workflowGetNodeListPojo);
                    return;
                } else if (formMap.containsKey(item.getFormId())) {
                    PaasFormEntity paasFormEntityExt = formMap.get(item.getFormId());
                    if (!FormUtil.haveWorkflowPermission(paasFormEntityExt.getBusinessType(), paasFormEntityExt.getSaasMark(), paasFormEntityExt.getDistributorMark())) {
                        // 不支持数据节点的表单
                        return;
                    }
                    WorkflowGetNodeListPojo workflowGetNodeListPojo = new WorkflowGetNodeListPojo(item.getWorkflowId(), item.getId(), item.getFormId(), item.getAppId(),
                            item.getMenuId(), item.getSaasMark(), item.getBusinessType(), paasFormEntityExt.getName(), item.getName(), 1, triggerNodeFlag);
                    nodeList.add(workflowGetNodeListPojo);
                    return;
                }
                WorkflowGetNodeListPojo workflowGetNodeListPojo = new WorkflowGetNodeListPojo(item.getWorkflowId(), item.getId(), item.getFormId(), item.getAppId(),
                        item.getMenuId(), item.getSaasMark(), item.getBusinessType(), "", item.getName(), 0, triggerNodeFlag);
                nodeList.add(workflowGetNodeListPojo);
            });
            return nodeList;
        } catch (Exception e) {
            LOGGER.error("WorkflowNodeUpdateSettings.updateNodeGetNodeList error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    protected void getFormIdSet(List<WorkflowOperationsPojo> operationsList, Set<Long> formIdSet, Set<Long> workOrderFormIdSet, Set<Long> workflowNodeIdSet) {
        operationsList.forEach(item->{
            if (Objects.equals(WorkflowValueTypeEnum.DYNAMIC_VALUE.getType(), item.getValueType())) {
                workflowNodeIdSet.add(item.getWorkflowNodeId());
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getBusinessType())) {
                    workOrderFormIdSet.add(item.getFormId());
                } else {
                    formIdSet.add(item.getFormId());
                }
            }
        });
    }


    protected void conditionGetFormIdSet(List<FilterCondition> conditionList, Set<Long> formIdSet, Set<Long> workOrderFormIdSet, Set<Long> workflowNodeIdSet) {
        conditionList.forEach(item->{
            if (Objects.equals(WorkflowValueTypeEnum.DYNAMIC_VALUE.getType(), item.getValueType())) {
                workflowNodeIdSet.add(item.getTargetWorkflowNodeId());
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getTargetBusinessType())) {
                    workOrderFormIdSet.add(item.getTargetFormId());
                } else {
                    formIdSet.add(item.getTargetFormId());
                }
            }
        });
    }

    protected Map<Long, WorkflowNodeEntity> getWorkflowNodeMap(Set<Long> workflowNodeIdSet, String corpid) {
        // 获取节点信息
        List<WorkflowNodeEntity> workflowNodeList = workflowNodeModel.getByIdIn(workflowNodeIdSet, corpid);
        Map<Long, WorkflowNodeEntity> workflowNodeEntityMap = new HashMap<>(workflowNodeList.size());
        workflowNodeList.forEach(item->{
            workflowNodeEntityMap.put(item.getId(), item);
        });
        return workflowNodeEntityMap;
    }

    /**
     * 获取排序字段
     * @param workflowNodeEntity
     * @param workOrderExplainMap
     * @param explainMap
     * @param orderField
     * @return
     */
    protected String getOrderFieldName(WorkflowNodeEntity workflowNodeEntity, Map<Long, Map<String, FieldAttrEntity>> workOrderExplainMap, Map<Long, Map<String, FieldAttrEntity>> explainMap,
                                       String orderField) {
        String orderFieldName = "";
        if (StringUtil.isEmpty(orderField)) {
            return orderFieldName;
        }
        if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), workflowNodeEntity.getBusinessType())
                && workOrderExplainMap.containsKey(workflowNodeEntity.getFormId()) && workOrderExplainMap.get(workflowNodeEntity.getFormId()).containsKey(orderField)) {
            orderFieldName = workOrderExplainMap.get(workflowNodeEntity.getFormId()).get(orderField).getAttrName();
        } else if (explainMap.containsKey(workflowNodeEntity.getFormId()) && explainMap.get(workflowNodeEntity.getFormId()).containsKey(orderField)){
            orderFieldName = explainMap.get(workflowNodeEntity.getFormId()).get(orderField).getAttrName();
        }
        return orderFieldName;
    }

    protected String getFormName(WorkflowNodeEntity workflowNodeEntity, String corpid) {
        String formName = "";
        if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), workflowNodeEntity.getBusinessType())) {
            WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByKey(workflowNodeEntity.getFormId(), corpid);
            if (Objects.nonNull(workOrderFormEntity)) {
                formName = workOrderFormEntity.getName();
            }
        } else {
            PaasFormEntity paasFormEntity = paasFormModel.getByKey(workflowNodeEntity.getFormId(), corpid);
            if (Objects.nonNull(paasFormEntity)) {
                formName = paasFormEntity.getName();
            }
        }
        return formName;
    }

    /**
     * 返回条件
     * @param conditionList
     * @param formId
     * @param businessType
     * @param explainMap
     * @param workOrderExplainMap
     * @param workflowNodeEntityMap
     * @return
     */
    protected List<FilterConditionVO> getReturnConditionList(List<FilterCondition> conditionList, Long formId, Integer businessType, Map<Long, Map<String, FieldAttrEntity>> explainMap,
                                                             Map<Long, Map<String, FieldAttrEntity>> workOrderExplainMap, Map<Long, WorkflowNodeEntity> workflowNodeEntityMap) {
        List<FilterConditionVO> condition = new ArrayList<>();
        conditionList.forEach(item->{
            String attrName = "";
            FieldAttrEntity targetField = null;
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), businessType) && workOrderExplainMap.containsKey(formId)
                    && Objects.nonNull(workOrderExplainMap.get(formId).get(item.getAttr())) ) {
                targetField = workOrderExplainMap.get(formId).get(item.getAttr());
                attrName = targetField.getAttrName();
            } else if (explainMap.containsKey(formId) && Objects.nonNull(explainMap.get(formId).get(item.getAttr()))){
                targetField = explainMap.get(formId).get(item.getAttr());
                attrName = targetField.getAttrName();
            }
            String targetNodeName = "";
            String targetFieldName = "";
            FieldAttrEntity fieldAttrEntity = null;
            if (Objects.equals(WorkflowValueTypeEnum.DYNAMIC_VALUE.getType(), item.getValueType())) {
                if (workflowNodeEntityMap.containsKey(item.getTargetFormId())) {
                    targetNodeName = workflowNodeEntityMap.get(item.getTargetWorkflowNodeId()).getName();
                }
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getTargetBusinessType()) && workOrderExplainMap.containsKey(item.getTargetFormId())
                        && Objects.nonNull(workOrderExplainMap.get(item.getTargetFormId()).get(item.getValueAttr())) ) {
                    fieldAttrEntity = workOrderExplainMap.get(item.getTargetFormId()).get(item.getValueAttr());
                } else if (explainMap.containsKey(item.getTargetFormId())
                        && Objects.nonNull(explainMap.get(item.getTargetFormId()).get(item.getValueAttr()))){
                    fieldAttrEntity = explainMap.get(item.getTargetFormId()).get(item.getValueAttr());
                }
            }
            FilterConditionVO filterConditionVO = new FilterConditionVO( targetNodeName, item.getTargetSaasMark(), item.getTargetBusinessType(), item.getTargetFormId(), item.getTargetWorkflowNodeId(),
                    item.getTriggerNodeFlag(), item.getAttr(), item.getFieldType(), attrName, item.getSymbol(), item.getValueType(), item.getValue(), item.getValueAttr(), item.getValueFieldType(),
                    targetFieldName, item.getRel());
            if (Objects.nonNull(fieldAttrEntity)) {
                filterConditionVO.setValueAttrName(fieldAttrEntity.getAttrName());
            }
            if (Objects.nonNull(targetField)) {
                filterConditionVO.setLinkedType(targetField.getLinkedType());
                filterConditionVO.setLinkInfo(targetField.getLinkInfo());
            }
            condition.add(filterConditionVO);
        });
        return condition;
    }

    protected List<WorkflowOperationsVO> getReturnOperationList(List<WorkflowOperationsPojo> operationsPojos, Long formId, Integer businessType,  Map<Long, Map<String, FieldAttrEntity>> explainMap,
                                                              Map<Long, Map<String, FieldAttrEntity>> workOrderExplainMap, Map<Long, WorkflowNodeEntity> workflowNodeEntityMap) {
        List<WorkflowOperationsVO> operations = new ArrayList<>();
        operationsPojos.forEach(item->{
            String attrName = "";
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), businessType) && workOrderExplainMap.containsKey(formId)
                    && Objects.nonNull(workOrderExplainMap.get(formId).get(item.getAttr())) ) {
                attrName = workOrderExplainMap.get(formId).get(item.getAttr()).getAttrName();
            } else if (explainMap.containsKey(formId) && Objects.nonNull(explainMap.get(formId).get(item.getAttr()))){
                attrName = explainMap.get(formId).get(item.getAttr()).getAttrName();
            }
            String targetNodeName = "";
            String targetFieldName = "";
            if (Objects.equals(WorkflowValueTypeEnum.DYNAMIC_VALUE.getType(), item.getValueType())) {
                if (workflowNodeEntityMap.containsKey(item.getWorkflowNodeId())) {
                    targetNodeName = workflowNodeEntityMap.get(item.getWorkflowNodeId()).getName();
                }
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getBusinessType()) && workOrderExplainMap.containsKey(item.getFormId())
                        && Objects.nonNull(workOrderExplainMap.get(item.getFormId()).get(item.getValueAttr())) ) {
                    targetFieldName = workOrderExplainMap.get(item.getFormId()).get(item.getValueAttr()).getAttrName();
                } else if (explainMap.containsKey(item.getFormId())
                        && Objects.nonNull(explainMap.get(item.getFormId()).get(item.getValueAttr()))){
                    targetFieldName = explainMap.get(item.getFormId()).get(item.getValueAttr()).getAttrName();
                }
            }

            WorkflowOperationsVO workflowOperationsVO = new WorkflowOperationsVO(targetNodeName, item.getWorkflowNodeId(), item.getFormId(), item.getBusinessType(), item.getSaasMark(), item.getTriggerNodeFlag(),
                    item.getAttr(), attrName, item.getFieldType(), item.getSymbol(), item.getValueType(), item.getValue(), item.getValueAttr(), item.getValueFieldType(), targetFieldName, item.getFormulaInfo());
            operations.add(workflowOperationsVO);
        });
        return operations;
    }

    protected boolean equals(Long formId, Integer businessType, Long targetFormId, Integer targetBusinessType) {
        return Objects.equals(businessType, targetBusinessType) && Objects.equals(targetFormId, formId);
    }

    /**
     * 校验操作字段
     * @param workflowNodeEntity
     * @param operationList
     * @param workflowGetPojo
     * @throws XbbException
     */
    protected void validateOperate(WorkflowNodeEntity workflowNodeEntity, Map<Long, WorkflowNodeEntity> nodeMap, List<WorkflowOperationsPojo> operationList, WorkflowGetPojo workflowGetPojo) throws XbbException {
        // 操作不能为空
        if (CollectionUtils.isEmpty(operationList)) {
            throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261004);
        }
        Long formId = workflowNodeEntity.getFormId();
        Integer businessType = workflowNodeEntity.getBusinessType();
        Map<String, FieldAttrEntity> targetExplain = WorkflowNodeUtil.getExplainMap(workflowGetPojo, businessType, formId);
        Map<Long, String> thisParentSet = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<String> targetParentSet = new HashSet<>();

        for (WorkflowOperationsPojo operationsPojo : operationList) {
            String targetAttr = operationsPojo.getAttr();
            if (StringUtil.isEmpty(targetAttr)) {
                throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261002);
            }
            String targetSubForm = "";
            List<String> targetFieldList = ExplainUtil.getAttrByPoint(targetAttr);
            if (targetFieldList.size() == BasicConstant.TWO) {
                targetAttr = targetFieldList.get(0);
                targetSubForm = targetFieldList.get(1);
                targetParentSet.add(targetAttr);
            }
            FieldAttrEntity targetField = targetExplain.get(targetAttr);
            if (Objects.isNull(targetField)) {
                throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006);
            }
            if (ExplainUtil.isSubForm(targetField.getFieldType())) {
                Map<String, FieldAttrEntity> subExplainMap = ExplainUtil.getExplainMapByList(targetField.getSubForm().getItems());
                targetField = subExplainMap.get(targetSubForm);
            }
            if (Objects.equals(WorkflowValueTypeEnum.DYNAMIC_VALUE.getType(), operationsPojo.getValueType())) {
                // 动态值
                if (StringUtil.isEmpty(operationsPojo.getValueAttr())) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261001);
                }
                if (!nodeMap.containsKey(operationsPojo.getWorkflowNodeId())) {
                    throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
                }
                WorkflowNodeEntity node = nodeMap.get(operationsPojo.getWorkflowNodeId());
                if (!equals(operationsPojo.getFormId(), operationsPojo.getBusinessType(), node.getFormId(), node.getBusinessType())) {
                    // 表单被更改
                    throw new XbbException(ProErrorCodeEnum.API_ERROR_260042);
                }
                String thisAttr = operationsPojo.getValueAttr();
                List<String> thisFieldList = ExplainUtil.getAttrByPoint(thisAttr);
                String thisSubForm = "";
                if (thisFieldList.size() == 2) {
                    thisAttr = thisFieldList.get(0);
                    thisSubForm = thisFieldList.get(1);
                    thisParentSet.put(operationsPojo.getWorkflowNodeId(), thisAttr);
                }
                Map<String, FieldAttrEntity> explainMap = WorkflowNodeUtil.getExplainMap(workflowGetPojo, operationsPojo.getBusinessType(), operationsPojo.getFormId());

                FieldAttrEntity fieldAttrEntity = explainMap.get(thisAttr);
                if (Objects.isNull(fieldAttrEntity)) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006);
                }
                if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType())) {
                    Map<String, FieldAttrEntity> subExplainMap = ExplainUtil.getExplainMapByList(fieldAttrEntity.getSubForm().getItems());
                    fieldAttrEntity = subExplainMap.get(thisSubForm);
                }
                if (Objects.isNull(fieldAttrEntity)) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006);
                }
                ConditionListHelp.validateTheForm(targetField, fieldAttrEntity, operationsPojo.getFormId(), formId,  businessType, operationsPojo.getBusinessType());
            } else if(Objects.equals(WorkflowValueTypeEnum.FIXED_VALUE.getType(), operationsPojo.getValueType())){
                boolean isFixed = (Objects.isNull(operationsPojo.getValue()) || StringUtil.isEmpty(operationsPojo.getValue().toString()));
                if (isFixed) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261003);
                }
            } else {
                // 公式解析
                String formula = operationsPojo.getFormulaInfo().getFormula();
                String[] formulaList = RegexUtil.getFormulaAttr(formula);
                for (int i = 0; i < formulaList.length; i++) {
                    String formulaStr = formulaList[i];
                    String[] formulaArray = WorkflowFormulaUtil.getAttrByFormula(formulaStr);
                    if (WorkflowFormulaUtil.validateFormula(formulaArray, formulaStr)) {
                        Long workflowNodeId = Long.valueOf(formulaArray[1]);
                        if (!nodeMap.containsKey(workflowNodeId)) {
                            throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
                        }
                        String formIdStr = formulaArray[2];
                        Long thisFormId;
                        Integer thisBusinessType = null;
                        if (formIdStr.contains(XbbRefTypeEnum.WORK_ORDER.getAlias())) {
                            thisBusinessType = XbbRefTypeEnum.WORK_ORDER.getCode();
                            thisFormId = Long.valueOf(formIdStr.replace(PaasConstant.WORK_ORDER, ""));
                        } else {
                            thisFormId = Long.valueOf(formIdStr);
                            PaasFormEntity paasFormEntity = workflowGetPojo.getFormMap().get(thisFormId);
                            if (Objects.nonNull(paasFormEntity)) {
                                thisBusinessType = paasFormEntity.getBusinessType();
                            }
                        }
                        WorkflowNodeEntity node = nodeMap.get(workflowNodeId);
                        if (!equals(thisFormId, thisBusinessType, node.getFormId(), node.getBusinessType())) {
                            // 表单不一致
                            throw new XbbException(ProErrorCodeEnum.API_ERROR_260042);
                        }
                        if (formulaStr.contains(FieldTypeEnum.SUB_FORM.getEsalias())) {
                            // 1.节点id.目标表单id.subForm_1.text_1
                            // 1.节点id.workOrder_工单表单id.subForm_1.text_1
                            String subForm = formulaArray[3];
                            thisParentSet.put(workflowNodeId, subForm);
                            String thisSubForm = formulaArray[4];
                            Map<String, FieldAttrEntity> explainMap = WorkflowNodeUtil.getExplainMap(workflowGetPojo, thisBusinessType,  thisFormId);

                            FieldAttrEntity fieldAttrEntity = explainMap.get(subForm);
                            if (Objects.isNull(fieldAttrEntity)) {
                                throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006);
                            }
                            if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType())) {
                                Map<String, FieldAttrEntity> subExplainMap = ExplainUtil.getExplainMapByList(fieldAttrEntity.getSubForm().getItems());
                                fieldAttrEntity = subExplainMap.get(thisSubForm);
                            }
                            if (Objects.isNull(fieldAttrEntity)) {
                                throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006);
                            }
                        } else {
                            // 1.节点id.目标表单id.text_1
                            // 1.节点id.workOrder_工单表单id.text_1
                            String subForm = formulaArray[3];
                            Map<String, FieldAttrEntity> explainMap = WorkflowNodeUtil.getExplainMap(workflowGetPojo, thisBusinessType,  thisFormId);
                            FieldAttrEntity fieldAttrEntity = explainMap.get(subForm);
                            if (Objects.isNull(fieldAttrEntity)) {
                                throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006);
                            }
                        }
                    }
                }
            }
        }
        if (thisParentSet.size() != targetParentSet.size() && targetParentSet.size() == 1 && thisParentSet.size() != 0) {
            // 插入数据时 目标表单为子表单时，不可以设置主字段，请重新选择；
            // 如果当前字段和目标表单字段都存在子表单，那么其子表单的数量应该一致；
            throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261015);
        }
    }


    protected void validateFilterCondition(WorkflowNodeEntity workflowNodeEntity, List<FilterCondition> filterCondition, WorkflowGetPojo workflowGetPojo) throws XbbException{
        boolean isSubForm = false;
        boolean isMainField = false;
        boolean isMainSub = false;
        boolean isSubMain = false;
        // 当前表单的子表单
        Set<String> thisSubFormSet = new HashSet<>();
        // 目标表单的子表单
        Set<String> targetSubFormSet = new HashSet<>();
        Long formId = workflowNodeEntity.getFormId();
        Integer businessType = workflowNodeEntity.getBusinessType();
        Map<String, FieldAttrEntity> targetSubExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, FieldAttrEntity> targetExplainMap = WorkflowNodeUtil.getExplainMap(workflowGetPojo, workflowNodeEntity.getBusinessType(), workflowNodeEntity.getFormId());
        for (FilterCondition item : filterCondition) {
            String attr = item.getAttr();
            String targetSubForm = "";
            List<String> attrList = ExplainUtil.getAttrByPoint(attr);
            if (attrList.size() == BasicConstant.TWO) {
                attr = attrList.get(0);
                targetSubForm = attrList.get(1);
                targetSubFormSet.add(attr);
            }
            if (!targetExplainMap.containsKey(attr)) {
                throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006);
            }
            FieldAttrEntity targetField = targetExplainMap.get(attr);
            if (Objects.equals(WorkflowValueTypeEnum.DYNAMIC_VALUE.getType(), item.getValueType())) {
                String valueAttr = item.getValueAttr();
                String thisSubForm = "";
                // 判断子表单字段，获取对应的字段
                if (valueAttr.contains(".")) {
                    String[] attrArray = valueAttr.split("\\.");
                    valueAttr = attrArray[0];
                    thisSubForm = attrArray[1];
                    thisSubFormSet.add(valueAttr);
                }
                if (StringUtil.isEmpty(valueAttr)) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261001);
                }
                Map<String, FieldAttrEntity> explainMap = WorkflowNodeUtil.getExplainMap(workflowGetPojo, item.getTargetBusinessType(), item.getTargetFormId());
                FieldAttrEntity fieldAttrEntity = explainMap.get(valueAttr);
                if (Objects.isNull(fieldAttrEntity)) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006);
                }
                if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType()) && ExplainUtil.isSubForm(targetField.getFieldType())) {
                    isSubForm = true;
                }
                if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType()) && !ExplainUtil.isSubForm(targetField.getFieldType())) {
                    isMainSub = true;
                }
                if (!ExplainUtil.isSubForm(fieldAttrEntity.getFieldType()) && ExplainUtil.isSubForm(targetField.getFieldType())) {
                    isSubMain = true;
                }
                if (!ExplainUtil.isSubForm(targetField.getFieldType()) && !ExplainUtil.isSubForm(fieldAttrEntity.getFieldType()) && !isMainField) {
                    isMainField = true;
                }
                Map<String, FieldAttrEntity> thisSubExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType())) {
                    List<? extends FieldAttrEntity> jsonArray = fieldAttrEntity.getSubForm().getItems();
                    thisSubExplainMap = ExplainUtil.getExplainMapByList(jsonArray);
                }
                if (StringUtil.isNotEmpty(thisSubForm)) {
                    fieldAttrEntity = thisSubExplainMap.get(thisSubForm);
                }
                if (ExplainUtil.isSubForm(targetField.getFieldType()) && targetSubExplainMap.isEmpty()) {
                    List<? extends FieldAttrEntity> jsonArray = targetField.getSubForm().getItems();
                    targetSubExplainMap= ExplainUtil.getExplainMapByList(jsonArray);
                }
                if (StringUtil.isNotEmpty(targetSubForm)) {
                    targetField = targetSubExplainMap.get(targetSubForm);
                }
                // 校验关联数据、系统关联字段和dataId之间的关联关系
                ConditionListHelp.validateTheForm(targetField, fieldAttrEntity,item.getTargetFormId(), formId, businessType, item.getTargetBusinessType());
            } else {
                // 固定值
                if (Objects.isNull(item.getValue()) || StringUtil.isEmpty(item.getValue().toString())) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261005);
                }
                if (!ExplainUtil.isSubForm(targetField.getFieldType())) {
                    isMainField = true;
                }
            }
        }
        if (thisSubFormSet.size() > 1) {
            // 过滤条件仅支持选择同一个子表单
            throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261008);
        }
        if (targetSubFormSet.size() > 1) {
            // 过滤条件仅支持选择同一个子表单
            throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261009);
        }
        if (isSubForm && !isMainField) {
            // 若过滤条件含子赋值子，则过滤条件须再添加一组主赋值主
            throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261010);
        }
        // 子赋值主isMainSub
        // 主赋值子isSubMain
        // 子赋值子 isSubForm
        boolean flag = (isMainSub && isSubMain) || (isMainSub && isSubForm) || (isSubMain && isSubForm);
        if (flag) {
            throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261011);
        }
    }

    /**
     * Description: 处理负责人协同人部分业务放开后的特殊处理; 在工作流优化需求中对一些关联产品的特殊逻辑也写在这边
     * @param workflowNodeEntity
	 * @param fieldPermission
     * @return void
     * @throws
     * @author 魏荣杰
     * @date 2022/4/21 16:49
     * @since
     */
    protected void addFieldPermission(WorkflowNodeEntity workflowNodeEntity, Map<String, FieldPermissionEntityExt> fieldPermission) throws XbbException {
        List<Integer> businessList = Arrays.asList(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), XbbRefTypeEnum.PAY_SHEET.getCode(), XbbRefTypeEnum.CONTACT.getCode(), XbbRefTypeEnum.SUPPLIER_CONTACT.getCode());
        List<Integer> handleProductBusinessList = Arrays.asList(XbbRefTypeEnum.QUOTATION.getCode(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode(),
                XbbRefTypeEnum.CONTRACT.getCode(), XbbRefTypeEnum.REFUND.getCode());
        Integer businessType = workflowNodeEntity.getBusinessType();
        if (businessList.contains(businessType)) {
            if (Objects.nonNull(fieldPermission) && !fieldPermission.containsKey("ownerId")) {
                fieldPermission.put("ownerId", new FieldPermissionEntityExt("ownerId", FieldTypeEnum.OWNERID.getType(), BasicConstant.ZERO, BasicConstant.ONE, BasicConstant.ZERO));
            }
            if (Objects.nonNull(fieldPermission) && !fieldPermission.containsKey("coUserId")) {
                fieldPermission.put("coUserId", new FieldPermissionEntityExt("coUserId", FieldTypeEnum.OWNERID.getType(), BasicConstant.ZERO, BasicConstant.ONE, BasicConstant.ZERO));
            }
        }
        if(Objects.equals(businessType, XbbRefTypeEnum.SALES_OPPORTUNITY.getCode()) && Objects.nonNull(fieldPermission)){
            FieldPermissionEntityExt linkCompetitorAttr = fieldPermission.get(SalesOpportunityEnum.LINK_COMPETITOR.getAttr());
            if (Objects.nonNull(linkCompetitorAttr)) {
                linkCompetitorAttr.setEditable(BasicConstant.ZERO);
            }
        }
        if (handleProductBusinessList.contains(businessType)) {
            List<String> unEditableFieldList = BusinessProductCompareEnum.getAllUnEditableFieldList(businessType);
            String prefix = null;
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(workflowNodeEntity.getFormId(), workflowNodeEntity.getCorpid());
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
            if (Objects.equals(XbbRefTypeEnum.QUOTATION.getCode(), businessType)) {
                prefix = QuotationEnum.PRODUCT.getAttr();
            }else if (Objects.equals(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode(), businessType)) {
                prefix = SalesOpportunityEnum.PRODUCTS.getAttr();
            }else if (Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), businessType)) {
                prefix = ContractEnum.PRODUCT.getAttr();
            }else if (Objects.equals(XbbRefTypeEnum.REFUND.getCode(), businessType)) {
                prefix = RefundEnum.PRODUCTS.getAttr();
            }
            FieldAttrEntity productEntity = explainMap.get(prefix);
            List<? extends FieldAttrEntity> itemList = productEntity.getSubForm().getItems();
            //需要根据最外层的关联产品可见与可编辑做一些特殊处理
            if (Objects.nonNull(productEntity) && Objects.equals(productEntity.getIsOpen(), BasicConstant.ONE) && MapUtils.isNotEmpty(fieldPermission)) {
                FieldPermissionEntityExt fieldPermissionEntityExt = fieldPermission.get(prefix);
                if (Objects.nonNull(fieldPermissionEntityExt)) {
                    Integer productEditable = fieldPermissionEntityExt.getEditable();
                    Integer productVisible = fieldPermissionEntityExt.getVisible();
                    for (FieldAttrEntity fieldAttrEntity : itemList) {
                        String key = fieldAttrEntity.getAttr();
                        String finalKey = prefix + "." + key;
                        if (!fieldPermission.containsKey(finalKey)) {
                            Integer editable = productEditable;
                            if (unEditableFieldList.contains(key)) {
                                editable = BasicConstant.ZERO;
                            }
                            fieldPermission.put(finalKey, new FieldPermissionEntityExt(key, fieldAttrEntity.getFieldType(), editable, productVisible, BasicConstant.ZERO));
                        }
                    }
                }
            }
        }
    }
}
